package l2ft.gameserver.ai;

import java.util.ArrayList;
import java.util.List;

import l2ft.commons.collections.CollectionUtils;
import l2ft.commons.util.Rnd;
import l2ft.gameserver.Config;
import l2ft.gameserver.geodata.GeoEngine;
import l2ft.gameserver.model.AggroList.AggroInfo;
import l2ft.gameserver.model.Creature;
import l2ft.gameserver.model.World;
import l2ft.gameserver.model.instances.FakePcInstance;
import l2ft.gameserver.model.instances.GuardInstance;
import l2ft.gameserver.model.instances.NpcInstance;
import l2ft.gameserver.utils.Location;

public class MainFakePc extends DefaultAI
{
	private int _team = -1;
	private List<NpcInstance> _npcFriends;
	private boolean _startAI = false;
	
	public MainFakePc(NpcInstance actor)
	{
		super(actor);
	}
	
	public MainFakePc(NpcInstance actor, int team) {
		super(actor);
	}
	
	public void setTeam(int team)
	{
		_team = team;
	}
	
	public Integer getTeam()
	{
		return _team;
	}
	
	public void setTarget(Creature target)
	{
		notifyEvent(CtrlEvent.EVT_AGGRESSION, target, 200000);
	}
	
	public void setMoveToPosition(int x, int y, int z)
	{
        clearTasks();
        addTaskMove(x, y, z, false);
	}
	
	@Override
	protected List<NpcInstance> activeFactionTargets()
	{
		//i dont have friends, if i dont have team
		if(getTeam() == null || getTeam().equals(0))
			return new ArrayList<NpcInstance>();
		_npcFriends = new ArrayList<>();
		
		//getting closest friends from the team
		for(NpcInstance npc : World.getAroundNpc(getActor()))
			if(!npc.isDead() && npc.isFakePc() && ((MainFakePc)npc.getAI()).getTeam().equals(getTeam()))
				_npcFriends.add(npc);
		
		return _npcFriends;
	}
	
	@Override
	protected void onEvtThink() 
	{
		if(_startAI)
			super.onEvtThink();
	}
	
	public void startAI()
	{
		_startAI = true;
		onEvtThink();
	}
	
	protected void friendDied(NpcInstance poorFriend)
	{
		activeFactionTargets().remove(poorFriend);
	}
	
	public void iDied(FakePcInstance me)
	{
		if(activeFactionTargets() == null)
			return;
		for(NpcInstance npc : activeFactionTargets())
			if(!npc.equals(me))
				((MainFakePc)npc.getAI()).friendDied(getActor());
	}
	
	protected void thinkAttack()
	{
		NpcInstance actor = getActor();
		if(actor.isDead())
			return;

		Location loc = actor.getSpawnedLoc();
		if(!actor.isInRange(loc, MAX_PURSUE_RANGE))
		{
			teleportHome();
			return;
		}

		if(doTask() && !actor.isAttackingNow() && !actor.isCastingNow())
		{
			if(!createNewTask())
			{
				clearTasks();
				actor.stopMove();

				setAttackTimeout(Long.MAX_VALUE);
				setAttackTarget(null);

				changeIntention(CtrlIntention.AI_INTENTION_ACTIVE, null, null);
			}
		}
	}
	
	@Override
	protected boolean canAttackCharacter(Creature target)
	{
		return !activeFactionTargets().contains(target);
	}
	
	@Override
	protected boolean thinkActive()
	{
		NpcInstance actor = getActor();
		if(actor.isActionsDisabled())
			return true;

		if(_randomAnimationEnd > System.currentTimeMillis())
			return true;

		if(_def_think)
		{
			if(doTask())
				clearTasks();
			return true;
		}

		long now = System.currentTimeMillis();
		if(now - _checkAggroTimestamp > Config.AGGRO_CHECK_INTERVAL)
		{
			_checkAggroTimestamp = now;
			System.out.println("thinking active");
			boolean aggressive = Rnd.chance(actor.getParameter("SelfAggressive", actor.isAggressive() ? 100 : 0));
			if(!actor.getAggroList().isEmpty() || aggressive)
			{
				List<Creature> chars = World.getAroundCharacters(actor);
				CollectionUtils.eqSort(chars, _nearestTargetComparator);
				
				//looking for target
				for(Creature cha : chars)
					if(cha.isNpc() && ((NpcInstance)cha).isFakePc())
					{
						MainFakePc chaAI = (MainFakePc) cha.getAI();
						if(getTeam() <= 0 || getTeam() != chaAI.getTeam())
						{
							if(checkAggression(cha))
								return true;
						}
					}
				
				for(Creature cha : chars)
				{
					if(aggressive || actor.getAggroList().get(cha) != null)
						if(checkAggression(cha))
							return true;
				}
			}
		}
		return false;
	}
	
	@Override
	protected boolean checkAggression(Creature target)
	{
		NpcInstance actor = getActor();
		if(target.isAlikeDead())
			return false;
		
		if (target.isNpc() && (target.isInvul() || activeFactionTargets().contains(target) || target instanceof GuardInstance))
			return false;

		if(target.isPlayable())
			return false;

		AggroInfo ai = actor.getAggroList().get(target);
		if(ai != null && ai.hate > 0)
		{
			if(!target.isInRangeZ(actor.getSpawnedLoc(), MAX_PURSUE_RANGE))
				return false;
		}
		else if(!target.isInRangeZ(actor.getSpawnedLoc(), actor.getAggroRange()))
			return false;
		
		if(!GeoEngine.canSeeTarget(actor, target, false))
			return false;
		
		actor.getAggroList().addDamageHate(target, 0, 2);

		if((target.isSummon() || target.isPet()))
			actor.getAggroList().addDamageHate(target.getPlayer(), 0, 1);

		startRunningTask(AI_TASK_ATTACK_DELAY);
		setIntention(CtrlIntention.AI_INTENTION_ATTACK, target);

		System.out.println("adding aggro");
		return true;
	}
	
	@Override
	protected boolean randomWalk() {
		return false;
	}
	
	@Override
	protected boolean randomAnimation() {
		return false;
	}
	
	@Override
	protected boolean isGlobalAggro() {
		return true;
	}
	
	@Override
	public boolean isGlobalAI() {
		return true;
	}
}
